#pragma once
#include <thread>
#include "match_queue.hpp"
#include "room_manager.hpp"
#include "user_table.hpp"
#include "online_manager.hpp"
class matcher
{
private:
    // 普通选手匹配队列
    match_queue<uint64_t> _q_normal;
    // 高手匹配队列
    match_queue<uint64_t> _q_high;
    // 大神匹配队列
    match_queue<uint64_t> _q_super;
    // 对应三个匹配队列的处理线程
    std::thread _th_normal;
    std::thread _th_high;
    std::thread _th_super;
    room_manager *_rm;
    user_table *_ut;
    online_manager *_om;

private:
    void handle_match(match_queue<uint64_t> &mq)
    {
        while (1)
        {
            // 1.判断队列人数是否大于2,小于2则阻塞等待
            while (mq.size() < 2)
            {
                mq.wait();
            }
            // 到这里表示人数够了,出队两个玩家
            uint64_t uid1, uid2;
            bool ret = mq.pop(uid1);
            if (ret == false)
            {
                continue;
            }
            ret = mq.pop(uid2);
            if (ret == false)
            {
                this->add(uid1);
                continue;
            }
            // 3.校验两个玩家是否在线,如果有人掉线,则要把另一个人重新加入队列
            websocket_server ::connection_ptr conn1;
            _om->get_conn_from_game_hall(uid1, conn1);
            if (conn1.get() == nullptr)
            {
                this->add(uid2);
                continue;
            }
            websocket_server ::connection_ptr conn2;
            _om->get_conn_from_game_hall(uid2, conn2);
            if (conn2.get() == nullptr)
            {
                this->add(uid1);
                continue;
            }
            // 4.为两个玩家创建房间,并将玩家加入房间中
            room_ptr rp = _rm->create_room(uid1, uid2);
            if (rp.get() == nullptr)
            {
                this->add(uid1);
                this->add(uid2);
                continue;
            }
            // 5.对两个玩家进行响应
            Json::Value resp;
            resp["optype"] = "match_success";
            resp["result"] = true;
            resp["room_id"] = (Json::UInt64)rp->id(); 
            std::string body;
            json_util::serialize(resp, body);
            conn1->send(body);
            conn2->send(body);
        }
    }
    void th_normal_entry() { return handle_match(_q_normal); }
    void th_high_entry() { return handle_match(_q_high); }
    void th_super_entry() { return handle_match(_q_super); }

public:
    matcher(room_manager *rm, user_table *ut, online_manager *om) : _rm(rm), _ut(ut), _om(om),
                                                                    _th_normal(std::thread(&matcher::th_normal_entry, this)),
                                                                    _th_high(std::thread(&matcher::th_high_entry, this)),
                                                                    _th_super(std::thread(&matcher::th_super_entry, this))
    {
        DBG_LOG("游戏匹配模块初始化完毕..");
    }
    bool add(uint64_t uid)
    {
        // 根据玩家的天梯分数,判断玩家档次,添加到不同的匹配队列
        // 1.根据用户ID,获取玩家信息
        Json::Value user;
        bool ret = _ut->select_by_id(uid, user);
        if (ret == false)
        {
            DBG_LOG("获取玩家:%lu 信息失败!", uid);
            return false;
        }
        int score = user["score"].asInt();
        // 2.添加到指定的队列中
        if (score < 2000)
        {
            _q_normal.push(uid);
        }
        else if (score >= 2000 && score < 3000)
        {
            _q_high.push(uid);
        }
        else
        {
            _q_super.push(uid);
        }
        return true;
    }
    bool del(uint64_t uid)
    {
        Json::Value user;
        bool ret = _ut->select_by_id(uid, user);
        if (ret == false)
        {
            DBG_LOG("获取玩家:%lu 信息失败!", uid);
            return false;
        }
        int score = user["score"].asInt();
        // 从指定队列删除
        if (score < 2000)
        {
            _q_normal.remove(uid);
        }
        else if (score >= 200 && score < 3000)
        {
            _q_high.remove(uid);
        }
        else
        {
            _q_super.remove(uid);
        }
        return true;
    }
};